home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 August: Tool Chest / Dev.CD Aug 99 TC.toast / What's New? / Development Kits / Hardware / Mac OS USB DDK v1.3a1 / Examples / PrinterClassDriver / Chooser.cp next >
Encoding:
Text File  |  1999-06-18  |  33.4 KB  |  1,159 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Chooser.cp
  3.  
  4.     Contains:    Chooser PACK code to support USB and serial printers
  5.  
  6.  
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History:
  11.  
  12.         10 Jun 98    gp        Lock our global area
  13.         9  Jun 98    gp        Clear the handle when creating the global storage
  14.                             Remove old global rsrc if its still there
  15.         8  May 98    gp        If we don't support USB then no need to init the name registry
  16.                             ptrs. This will prevent the name registry alert from
  17.                             displaying on non PCI PowerMacs if we only support serial.
  18.         8  May 98    gp        Moved creation of model index array to InitPack
  19.         21 Apr 98    gp        If only 1 USB printer is listed and no previous selection
  20.                             then select it. Added new routines to save selected printer's
  21.                             name and USB path If previously selected printer is not available
  22.                             display an alert.
  23.         27 Mar 98    gp        Routines to access connection info from in rsrc
  24.         26 Mar 98    gp        Release model index storage. Add support for serial ports
  25.         25 Mar 98     gp        Change code to store our global space our rsrc
  26.         21 Mar 98     gp        Created
  27.  
  28.     To Do:
  29. */
  30.  
  31. #ifndef __Chooser__
  32. #include "Chooser.h"
  33. #endif
  34.  
  35. #ifndef __COMMON__
  36. #include "Common.h"
  37. #endif
  38.  
  39. #ifndef __UTILS__
  40. #include "Utils.h"
  41. #endif
  42.  
  43. #ifndef __DEVICES__
  44. #include <Devices.h>
  45. #endif
  46.  
  47. #ifndef __RESOURCES__
  48. #include <Resources.h>
  49. #endif
  50.  
  51. #ifndef __TEXTUTILS__
  52. #include <TextUtils.h>
  53. #endif
  54.  
  55. #ifndef __COMMRESOURCES__
  56. #include <CommResources.h>
  57. #endif
  58.  
  59. #ifndef __CRMSERIALDEVICES__
  60. #include <CRMSerialDevices.h>
  61. #endif
  62.  
  63. #ifndef __MIXEDMODE__
  64. #include <MixedMode.h>
  65. #endif
  66.  
  67. #ifndef __CODEFRAGMENTS__
  68. #include <CodeFragments.h>
  69. #endif
  70.  
  71. #ifndef __DIALOGS__
  72. #include <dialogs.h>
  73. #endif
  74.  
  75. #ifndef __SafeNameRegistry__
  76. #include "SafeNameRegistry.h"
  77. #endif
  78.  
  79. /******************************************************************************
  80.     Typedefs
  81.  ******************************************************************************/
  82.  
  83. // This structure is passed to AddPrintertoList (a callback routine) from
  84. // SearchForUSBPrinters. Its used to hold data which is needed to add a
  85. // printer name to the Chooser's printer list
  86. typedef struct
  87. {
  88.     ListHandle    list;            // the printer list
  89.     Cell        insertcell;        // where to insert an entry
  90.     short        modelIndex;        // index into STR# holding printer models supported
  91. } AddPrintertoListCallBackStruct, *AddPrintertoListCallBackStructPtr;
  92.  
  93. // This structure is passed to AddPorttoList (a callback routine) from
  94. // SearchForSerialPorts. Its used to hold data which is needed to add a
  95. // serial port to the Chooser's printer list
  96. typedef struct
  97. {
  98.     ListHandle    list;            // the printer list
  99.     Cell        insertcell;        // where to insert an entry
  100. } AddPorttoListCallBackStruct, *AddPorttoListCallBackStructPtr;
  101.  
  102. // typedef for callback routine used in SearchForUSBPrinters when a printer
  103. // entry is found in the name registry
  104. typedef void (*FoundUSBPrinterProcPtr) ( RegEntryID* aPrinterEntry, void* userData);
  105.  
  106. // typedef for callback routine used in SearchForSerialPorts when a port
  107. // entry is found in the name registry
  108. typedef void (*FoundSerialPortProcPtr) ( CRMSerialPtr aPort, void* userData);
  109.  
  110. /******************************************************************************
  111.     Prototypes
  112.  ******************************************************************************/
  113.  
  114. short    CountUSBPrinters(void);
  115. void    FillPrinterList( ListHandle list );
  116. void    AddPrintertoList( RegEntryID* aPrinterEntry, void* userData );
  117. void    CountAPrinter( RegEntryID* aPrinterEntry, void* userData );
  118. void    SearchForUSBPrinters( StringPtr modelPath, FoundUSBPrinterProcPtr callback, void* userData );
  119.  
  120. short    CountSerialPorts(void);
  121. void    AddPorttoList( CRMSerialPtr aPort, void* userData );
  122. void    CountAPort(  CRMSerialPtr aPort, void* userData );
  123. void    SearchForSerialPorts(FoundSerialPortProcPtr callback, void* userData);
  124.  
  125. OSErr    ShowSelection (ListHandle list, StringPtr zoneName);
  126. OSErr    Select (ListHandle list, StringPtr zoneName, long rowNum);
  127.  
  128. void    SetConnectionType(short    type);
  129. short    GetConnectionType(void);
  130. OSErr    InitPack(void);
  131.  
  132. Boolean    SaveSelectedUSBPrinter( Cell selectedCell, ListHandle list );
  133. void    SaveSelectedPrinterName( Cell selectedCell, ListHandle list);
  134. Handle    GetLastSelectedUSBPrinter();
  135.  
  136. /******************************************************************************
  137.     Constants
  138.  ******************************************************************************/
  139.  
  140. #define        kHilited    0
  141. #define        kUnHilited    255
  142.  
  143. #define        kGlobalType        'wxyz'        // made up type
  144. #define        kGlobalID        128
  145.  
  146. #define        kConnectionType        'CTYP'
  147. #define        kConnectionTypeID    1000
  148.  
  149. // Possible selected types. Used in ConnectionType rsrc
  150. #define        kNone            0
  151. #define        kSerial            1
  152. #define        kUSB            2
  153.  
  154. #define     kAPortName    "\p.AIn"    // To compare input device name when searching serial devices in the Comm Tool Box's List
  155. #define        kBPortName    "\p.BIn"    // To comapre input device name when searching serial devices in the Comm Tool Box's List
  156.  
  157. #define        kPrinterNotAvailable    3100
  158. /*-----------------------------------------------------------------------------*
  159.  
  160.     SaveSelectedUSBPrinter
  161.     
  162.     Desc:        Saves the name registry path of the selected printer
  163.  
  164.     In:            - the cell of the selected printer
  165.                 - the Chooser's printer list
  166.                 - the row of the selected cell
  167.                 
  168.     Out:        true if the path was saved
  169.                 false if the path wasn't saved
  170.  
  171.     
  172.  *-----------------------------------------------------------------------------*/
  173. Boolean    SaveSelectedUSBPrinter( Cell selectedCell, ListHandle list )
  174. {
  175.     Handle        lastPrinterString=nil;    // the previous selected printer 
  176.     Str255         selectedPrinterName;    // name of the selected printer
  177.     Str255        modelString;    // path in name registry of printer model
  178.     Boolean        saved=false;            // was the selected printer saved properly
  179.  
  180.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  181.  
  182.     gGlobals = GetGlobalStorage();
  183.  
  184.     // Get the name of the printer that was selected out of the list
  185.     GetNameFromCell (selectedPrinterName, selectedCell, list);
  186.     // get the last selected printer
  187.     lastPrinterString = GetLastSelectedUSBPrinter();
  188.  
  189.     // get the model path
  190.     GetIndString(modelString, kUSBModelPathString, *((**gGlobals).modelIndex+selectedCell.v) );
  191.     if( modelString[0] != 0 && lastPrinterString != nil) 
  192.     {                
  193.         Handle    tempHandle=nil;
  194.         // create the selected printer's name registry path
  195.         AppendPStr( (StringPtr) modelString, "\p:" );
  196.         AppendPStr( (StringPtr) modelString, selectedPrinterName );
  197.         
  198.         HLock( lastPrinterString );
  199.         BlockMove( modelString, *lastPrinterString, modelString[0]+1 );
  200.         HUnlock( lastPrinterString );
  201.  
  202.         // save the selected printers's name registry path
  203.         ChangedResource( lastPrinterString );
  204.         SetConnectionType( kUSB );
  205.         
  206.         WriteResource(lastPrinterString);
  207.         saved = true;
  208.     }
  209.     return saved;
  210. }
  211.  
  212. /*-----------------------------------------------------------------------------*
  213.  
  214.     GetLastSelectedUSBPrinter
  215.     
  216.     Desc:        Returns the name registry path of the last selected USB printer
  217.  
  218.     In:            None
  219.                 
  220.     Out:        Handle to a STR containing the name registry path of the last
  221.                 selected USB printer
  222.  
  223.     History:
  224.     
  225.     21 Apr 98    gp        Created
  226.     
  227.  *-----------------------------------------------------------------------------*/
  228. Handle    GetLastSelectedUSBPrinter()
  229. {
  230.     Handle            printerString=nil;    // the full path in name registry of last selected USB printer
  231.  
  232.     printerString = Get1Resource( 'STR ', kUSBPrinterPathString );
  233.     if( printerString == nil ) {
  234.         DebugStr("\pIn GetLastSelectedUSBPrinter. THIS SHOULD NEVER HAPPEN");
  235.     }
  236.     return printerString;
  237. }
  238.  
  239. /*-----------------------------------------------------------------------------*
  240.  
  241.     SaveSelectedPrinterName
  242.     
  243.     Desc:        Saves the name of the selected printer in our rsrc
  244.  
  245.     In:            - the cell of the selected printer
  246.                 - the Choosers printer list handle
  247.                 
  248.     Out:        None
  249.  
  250.     History:
  251.     
  252.     21 Apr 98    gp        Created
  253.     
  254.  *-----------------------------------------------------------------------------*/
  255. void    SaveSelectedPrinterName( Cell selectedCell, ListHandle list)
  256. {
  257.     Handle            printerString=nil;        // path in name registry of current USB printer
  258.     Str255             selectedPrinterName;            // name of the selected printer
  259.  
  260.     GetNameFromCell (selectedPrinterName, selectedCell, list);
  261.  
  262.     // save the name of the printer
  263.     printerString = (Handle) Get1Resource( 'STR ', kPrinterNameString );
  264.     if( selectedPrinterName[0] != 0 && printerString != nil) 
  265.     {
  266.         HLock( printerString );
  267.         BlockMove( selectedPrinterName, *printerString, selectedPrinterName[0]+1 );
  268.         HUnlock( printerString );
  269.  
  270.         // save the newly selected printer's name
  271.         ChangedResource( printerString );
  272.         WriteResource(printerString);
  273.     }
  274.  
  275. }
  276.  
  277. /*-----------------------------------------------------------------------------*
  278.  
  279.     GetConnectionType
  280.     
  281.     Desc:        Gets the connection type for the last selected printer
  282.                 from our rsrc
  283.  
  284.     In:            None
  285.                 
  286.     Out:        kNone, kSerial or kUSB
  287.  
  288.     History:
  289.     
  290.     27 Mar 98    gp        Created
  291.     
  292.  *-----------------------------------------------------------------------------*/
  293. short    GetConnectionType(void)
  294. {
  295.     Handle    connection;
  296.  
  297.     connection = (Handle) Get1Resource( kConnectionType, kConnectionTypeID );
  298.     return (**(short**)connection);
  299.  
  300. }
  301.  
  302. /*-----------------------------------------------------------------------------*
  303.  
  304.     SetConnectionType
  305.     
  306.     Desc:        Saves the connection type of the selected printer in our rsrc
  307.  
  308.     In:            kNone, kSerial or kUSB
  309.                 
  310.     Out:        None
  311.     
  312.     History:
  313.     
  314.     27 Mar 98    gp        Created
  315.     
  316.  *-----------------------------------------------------------------------------*/
  317. void    SetConnectionType(short    type)
  318. {
  319.     Handle    connection;
  320.  
  321.     connection = (Handle) Get1Resource( kConnectionType, kConnectionTypeID );
  322.     (**(short**)connection) = type;
  323.     ChangedResource( connection );
  324.     WriteResource( connection );
  325. }
  326.  
  327. /*-----------------------------------------------------------------------------*
  328.  
  329.     CountAPort
  330.     
  331.     Desc:        Callback routine for CountSerialPorts. It increments the
  332.                 ptr to user data thus incrementing the count of serial ports.
  333.  
  334.     In:            - A port to a CRMSerialPtr struct
  335.                 - A ptr to user data
  336.  
  337.     Out:        None
  338.     
  339.     History:
  340.     
  341.     26 Mar 98    gp        Created
  342.     
  343.  *-----------------------------------------------------------------------------*/
  344. void    CountAPort(  CRMSerialPtr aPort, void* userData )
  345. {
  346.     // we're only interested in .ain and .bin
  347.     if ( (PStrEqualCaseInsensitive((unsigned char*) kBPortName, *(aPort->inputDriverName)) ) ||
  348.         (PStrEqualCaseInsensitive((unsigned char*) kAPortName, *(aPort->inputDriverName)) ))
  349.     {
  350.             *((short*) userData) +=1;
  351.     }
  352. }
  353.  
  354. /*-----------------------------------------------------------------------------*
  355.  
  356.     AddPorttoList
  357.     
  358.     Desc:        Adds a serial port the the Chooser's list. We're only interested
  359.                 in modem and printer ports
  360.  
  361.     In:            - A port to a CRMSerialPtr struct
  362.                 - A ptr to user data. This should be a ptr to a 
  363.                   AddPorttoListCallBackStruct
  364.  
  365.     Out:        None
  366.     
  367.     History:
  368.     
  369.     26 Mar 98    gp        Created
  370.     
  371.  *-----------------------------------------------------------------------------*/
  372. void    AddPorttoList( CRMSerialPtr aPort, void* userData )
  373. {
  374.     AddPorttoListCallBackStructPtr     addPortStruct=(AddPorttoListCallBackStructPtr) userData;
  375.  
  376.     // we're only interested in .ain and .bin
  377.     if ( PStrEqualCaseInsensitive((unsigned char*) kBPortName, *(aPort->inputDriverName)) )
  378.     {
  379.         LAddRow(1, addPortStruct->insertcell.v, addPortStruct->list);
  380.         LSetCell( "Printer", 7, addPortStruct->insertcell, addPortStruct->list );
  381.         addPortStruct->insertcell.v++;
  382.     }
  383.     
  384.     if ( PStrEqualCaseInsensitive((unsigned char*) kAPortName, *(aPort->inputDriverName)) )
  385.     {
  386.         LAddRow(1, addPortStruct->insertcell.v, addPortStruct->list);
  387.         LSetCell( "Modem", 5, addPortStruct->insertcell, addPortStruct->list );
  388.         addPortStruct->insertcell.v++;
  389.     }
  390. }
  391.  
  392. /*-----------------------------------------------------------------------------*
  393.  
  394.     CountSerialPorts
  395.     
  396.     Desc:        Returns the number of serial ports
  397.  
  398.     In:            None
  399.                 
  400.     Out:        The number of serial ports
  401.     
  402.     History:
  403.     
  404.     26 Mar 98    gp        Created
  405.     
  406.  *-----------------------------------------------------------------------------*/
  407. short    CountSerialPorts(void)
  408. {
  409.     short    numberOfPorts=0;
  410.  
  411.     SearchForSerialPorts( (FoundSerialPortProcPtr) &CountAPort, &numberOfPorts );
  412.  
  413.     return numberOfPorts;
  414. }
  415.  
  416. /*-----------------------------------------------------------------------------*
  417.  
  418.     SearchForSerialPorts
  419.     
  420.     Desc:        Searchs for serial ports on this machine
  421.  
  422.     In:            - A callback routine which gets called when a printer is found
  423.                 - A ptr to user data
  424.  
  425.     Out:        None
  426.     
  427.     History:
  428.     
  429.     26 Mar 98    gp        Created
  430.     
  431.  *-----------------------------------------------------------------------------*/
  432. void    SearchForSerialPorts(FoundSerialPortProcPtr callback, void* userData)
  433. {
  434.     CRMErr                theErr;                // comm rsrc manager error
  435.     CRMRec                commRec;            // communications resource manager record
  436.     CRMRecPtr            commRecPtr;            // ptr to a communication resource record in the queue
  437.     CRMSerialPtr        commRecSerialPtr;    // ptr to serial record inside comm resource record
  438.     long            curSerialDeviceID = 0;     // initially set to zero, so we get all serial devices
  439.  
  440.     theErr = InitCRM(); // Initialize the Communications Resource Manager
  441.  
  442.     // now search for serial devices
  443.     while (theErr == noErr)
  444.     {
  445.         commRec.crmDeviceType = crmSerialDevice; // look for serial devices
  446.         commRec.crmDeviceID = curSerialDeviceID; // look for a device number greater than curSerialDeviceID
  447.     
  448.         commRecPtr = &commRec;
  449.         commRecPtr = CRMSearch(commRecPtr);    // Search  queue for each serial device
  450.     
  451.         if (commRecPtr != nil)
  452.         {
  453.             // get the Serial record pointer
  454.             commRecSerialPtr = (CRMSerialPtr)(*commRecPtr).crmAttributes;
  455.             
  456.             callback( commRecSerialPtr, userData);    // found a port
  457.             
  458.             // Set device ID for next search
  459.             curSerialDeviceID = (*commRecPtr).crmDeviceID;
  460.         }
  461.         else
  462.         {
  463.             theErr = 1; // game over, no more serial devices
  464.         }
  465.     }
  466. }
  467.  
  468. /*-----------------------------------------------------------------------------*
  469.  
  470.     SearchForUSBPrinters
  471.     
  472.     Desc:        Searches thru a printer model entry in the name registry
  473.                 looking for a model's printers. When one is found a call is 
  474.                 issued to the clients callback routine for further processing
  475.  
  476.     In:            - A pstring full path in the name registry of a printer model
  477.                 - A callback routine which gets called when a printer is found
  478.                 - A ptr to user data
  479.                 
  480.     Out:        None
  481.     
  482.     History:
  483.     
  484.     24 Feb 98    gp        Created
  485.     
  486.  *-----------------------------------------------------------------------------*/
  487. void    SearchForUSBPrinters( StringPtr modelPath, FoundUSBPrinterProcPtr callback, void* userData )
  488. {
  489.  
  490.     RegEntryID        theModelEntry;        // the model node supported by the driver
  491.     RegEntryID        aPrinterEntry;        // a printer node in the name registry
  492.     RegEntryIterationOp iterOp;            // name registry iterator op code
  493.     RegEntryIter    printerIterator;    // used to iterate child nodes of printer model
  494.     Boolean            donePrinters    = false;    // NameRegistry param tell when we're done
  495.     OSStatus        err             = noErr;    // error from name registry calls
  496.  
  497.     // name registry only deals with c strings
  498.     p2cstr( (StringPtr) modelPath );
  499.  
  500.     // look up the node for the printer model requested
  501.     err = SafeRegistryEntryIDInit(&theModelEntry);
  502.     err = SafeRegistryCStrEntryLookup( nil, (char*) modelPath, &theModelEntry );
  503.  
  504.     if( err == noErr ) 
  505.     {
  506.         // create an iterator to look at the child nodes for our printer model entry
  507.         iterOp = kRegIterChildren;
  508.  
  509.         err = SafeRegistryEntryIterateCreate( &printerIterator );
  510.         err = SafeRegistryEntryIterateSet(&printerIterator, &theModelEntry);
  511.         
  512.         if( err == noErr )
  513.         {
  514.             // look for a model's connected printers
  515.             do
  516.             {
  517.                 err = SafeRegistryEntryIterate( &printerIterator, iterOp, &aPrinterEntry, &donePrinters );
  518.                 if( !donePrinters && err == noErr )
  519.                     callback(&aPrinterEntry, userData);    // found a printer
  520.  
  521.                 iterOp = kRegIterContinue;
  522.             } while( !donePrinters && err == noErr );
  523.             // end while for printers
  524.         }
  525.         SafeRegistryEntryIterateDispose(&printerIterator);
  526.     }
  527.  
  528.     SafeRegistryEntryIDDispose( &theModelEntry );
  529.     c2pstr( (char*) modelPath );
  530.  
  531. }
  532.  
  533. /*-----------------------------------------------------------------------------*
  534.  
  535.     CountAPrinter
  536.     
  537.     Desc:        Callback routine for CountUSBPrinters. It increments the
  538.                 ptr to user data thus incrementing the count of USB printers.
  539.  
  540.     In:            - A printer entry in the name registry
  541.                 - A ptr to user data
  542.                 
  543.     Out:        The number of USB printers in the name registry
  544.     
  545.     History:
  546.     
  547.     24 Feb 98    gp        Created
  548.     
  549.  *-----------------------------------------------------------------------------*/
  550.  
  551. void    CountAPrinter(  RegEntryID* aPrinterEntry, void* userData )
  552. {
  553.     *((short*) userData) +=1;
  554. }
  555.  
  556. /*-----------------------------------------------------------------------------*
  557.  
  558.     CountUSBPrinters
  559.     
  560.     Desc:        Returns the number of connected USB printers associated with this driver
  561.  
  562.     In:            None
  563.                 
  564.     Out:        The number of USB printers in the name registry
  565.     
  566.     History:
  567.     
  568.     24 Feb 98    gp        Created
  569.     
  570.  *-----------------------------------------------------------------------------*/
  571.  
  572. short    CountUSBPrinters()
  573. {
  574.     short            numberOfPrinters=0;    // return value for number of USB printers
  575.     Str255            modelPath;            // pstring path in a supported printer model
  576.     short            i;                    // counter
  577.  
  578.     i=1;
  579.     // read a supported printer's name registry model path
  580.     GetIndString(modelPath, kUSBModelPathString, i);
  581.     
  582.     while( (char*) modelPath[0] != 0 )        // if len is zero then no more models
  583.     {
  584.         SearchForUSBPrinters( modelPath, (FoundUSBPrinterProcPtr) &CountAPrinter, &numberOfPrinters );
  585.         i++;
  586.         // read another supported printer's name registry model path
  587.         GetIndString(modelPath, kUSBModelPathString, i);
  588.     }
  589.  
  590.     return numberOfPrinters;
  591. }
  592.  
  593. /*-----------------------------------------------------------------------------*
  594.  
  595.     AddPrintertoList
  596.     
  597.     Desc:        Adds an USB printer to the Chooser's printer list by extracting
  598.                 the name from the name registry
  599.  
  600.     In:            - A printer entry in the name registry
  601.                 - A ptr to user data. This should be a ptr to a 
  602.                   AddPrintertoListCallBackStruct 
  603.                 
  604.     Out:        The number of USB printers in the name registry
  605.     
  606.     History:
  607.     
  608.     24 Feb 98    gp        Created
  609.     
  610.  *-----------------------------------------------------------------------------*/
  611. void    AddPrintertoList( RegEntryID* aPrinterEntry, void* userData )
  612. {
  613.     OSStatus        err = noErr;        // error from name registry call
  614.     Str255            nodeName;            // the name of the printer
  615.     RegPropertyValueSize    nameSize;    // size of name buffer
  616.     AddPrintertoListCallBackStructPtr     fillListStruct=(AddPrintertoListCallBackStructPtr) userData;
  617.     USBGlobalsHandle    gGlobals=nil;    // our global data area
  618.  
  619.     gGlobals = GetGlobalStorage();
  620.  
  621.     nameSize = sizeof( nodeName );
  622.     // grab name of printer in name registyr
  623.     err = SafeRegistryPropertyGet( aPrinterEntry, "name", &nodeName, &nameSize );
  624.     
  625.     if( err == noErr ) {
  626.         // stick it in the printer list
  627.         LAddRow(1, fillListStruct->insertcell.v, fillListStruct->list);
  628.         LSetCell( nodeName, nameSize-1, fillListStruct->insertcell, fillListStruct->list );
  629.         
  630.         // save info about which model (STR#) this printer belongs to
  631.         *((**gGlobals).modelIndex+fillListStruct->insertcell.v) = fillListStruct->modelIndex;
  632.         fillListStruct->insertcell.v++;
  633.     }
  634. }
  635.  
  636. /*-----------------------------------------------------------------------------*
  637.  
  638.     FillUSBList
  639.     
  640.     Desc:        Fills the printer list with the number of USB printers
  641.  
  642.     In:            - The Chooser's printer list handle
  643.                 
  644.     Out:        None
  645.     
  646.     History:
  647.     
  648.     24 Feb 98    gp        Created
  649.     
  650.  *-----------------------------------------------------------------------------*/
  651. void    FillPrinterList( ListHandle list )
  652. {
  653.     AddPrintertoListCallBackStruct    userData;    // struct needed by callback routine
  654.     AddPorttoListCallBackStruct        userPortData;    // struct needed by callback routine
  655.     Str255        modelPath;                        // pstring path in a supported printer model
  656.     short        i;                                // counter
  657.  
  658.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  659.     
  660.     gGlobals = GetGlobalStorage();
  661.     
  662.     userPortData.insertcell.v = 0;
  663.     // if we support serial ports then list serial ports
  664.     if( (**gGlobals).supportsSerial == true ) {
  665.         userPortData.list = list;
  666.         userPortData.insertcell.h = 0;
  667.  
  668.         // add the serial ports to the chooser list
  669.         SearchForSerialPorts( (FoundSerialPortProcPtr) &AddPorttoList, (void*) &userPortData );
  670.     }
  671.  
  672.     // if we support USB then list USB printers
  673.     if( (**gGlobals).supportsUSB == true ) {
  674.         userData.list = list;
  675.         userData.insertcell.v = userPortData.insertcell.v;
  676.         userData.insertcell.h = 0;
  677.  
  678.         i=1;
  679.         // read a supported printer's name registry model path
  680.         GetIndString(modelPath, kUSBModelPathString, i);
  681.         while( (char*) modelPath[0] != 0 )        // if len is zero then no more models
  682.         {
  683.             userData.modelIndex = i;
  684.             // add the USB printers to the chooser list
  685.             SearchForUSBPrinters( modelPath, (FoundUSBPrinterProcPtr) &AddPrintertoList, (void*) &userData );
  686.             i++;
  687.             // read another supported printer's name registry model path
  688.             GetIndString(modelPath, kUSBModelPathString, i);
  689.         }
  690.     }
  691. }
  692.  
  693. /*-----------------------------------------------------------------------------*
  694.     
  695.     ShowSelection
  696.     
  697.     Desc:        Hilites the currently selected printer in the printer list
  698.  
  699.     In:            - Handle to Mac List Mgr list
  700.                 - Name of zone we are currently in
  701.                 
  702.     Out:        OS error if any
  703.     
  704.     History:
  705.     
  706.     21 Apr 98    gp        If only 1 USB printer is listed and no previous selection
  707.                         then select it. If previously selected printer is not available
  708.                         display an alert.
  709.     9  Apr 98    gp        Use hlock not hunlock. Moved foundcell outside loop
  710.     21 Mar 98    gp        Extract previously selected printer from our rsrc
  711.     24 Feb 98    gp        Created
  712.     
  713.  *-----------------------------------------------------------------------------*/
  714. OSErr    ShowSelection (ListHandle list, StringPtr zoneName)
  715. {
  716.     Cell            cell;                            // used to iterate thru printer list, shows selected cell
  717.     Str255            nameBuffer;                        // selected AT printer is on the net, search for the cell
  718.     Boolean            foundCell = false;                // found a cell with same name as selected printer
  719.     Handle            selectedPrinter;                // name of the selected printer
  720.  
  721.     Str255            modelString;                    // path in name registry of printer model
  722.     Handle            printerString;                    // the full path in name registry of selected USB printer
  723.     RegEntryID        thePrinterEntry;                // the node of the USB printer node selected
  724.     OSStatus        err             = noErr;        // err encountered when calling name registry API
  725.     short            hiliteState = kUnHilited;        // hilite state of the button
  726.     USBGlobalsHandle    gGlobals=nil;                // our global data area
  727.     short            connectionType;                    // what type of printer connection, serial or USB
  728.     
  729.     gGlobals = GetGlobalStorage();
  730.  
  731.     // get the current selected printer out of the rsrc
  732.     printerString = GetLastSelectedUSBPrinter();
  733.     if( printerString == nil ) {
  734.         return noErr;
  735.     }
  736.  
  737.     // extract printer name for use later
  738.     selectedPrinter = (Handle) Get1Resource( 'STR ', kPrinterNameString );
  739.     if(  selectedPrinter == nil)
  740.         return noErr;
  741.     HLock( selectedPrinter );
  742.  
  743.     connectionType = GetConnectionType();
  744.     switch( connectionType ) {
  745.         case kSerial:
  746.             SetPt (&cell, 0, 0);
  747.  
  748.             // look for the port
  749.             while ( (!foundCell) && (cell.v < (*list)->dataBounds.bottom) )
  750.             {
  751.                 GetNameFromCell(nameBuffer, cell, list);
  752.  
  753.                 // if it equals the name of the current cell, we found the printer
  754.                 if ( EqualString( (StringPtr) *selectedPrinter, nameBuffer, true, true) ) {
  755.                     foundCell = true;
  756.                 } else
  757.                     cell.v++;
  758.             }
  759.             if( !foundCell )
  760.                 StopAlert(kPrinterNotAvailable, nil);
  761.             break;
  762.         case kUSB:
  763.             HLock( printerString );
  764.  
  765.             // name registry only deals with c strings
  766.             p2cstr( (StringPtr) *printerString );
  767.  
  768.             // check to make sure printer is still in name registry before selecting
  769.             SafeRegistryEntryIDInit(&thePrinterEntry);
  770.             err = SafeRegistryCStrEntryLookup( nil, (char*) *printerString, &thePrinterEntry );
  771.             
  772.             // clean up
  773.             c2pstr( (char*) *printerString );
  774.             HUnlock( printerString );
  775.             SafeRegistryEntryIDDispose( &thePrinterEntry );
  776.  
  777.             // if printer is no longer connected put up an alert
  778.             if( err ) {
  779.                 StopAlert(kPrinterNotAvailable, nil);
  780.             } else {
  781.                 // since user could have connected or disconnect other printers from USB bus
  782.                 // we need to find the exact place in the list and hilite it
  783.  
  784.                 SetPt (&cell, 0, 0);
  785.  
  786.                 // loop through all the printers in the list seeing if there is a
  787.                 // match for the driver's selected printer
  788.                 while ( (!foundCell) && (cell.v < (*list)->dataBounds.bottom) )
  789.                 {
  790.                     GetNameFromCell(nameBuffer, cell, list);
  791.  
  792.                     // If the name is one of our reserved rows and
  793.                     // it equals the name of the current cell, we found a possible printer
  794.                     
  795.                     if ( EqualString( (StringPtr) *selectedPrinter, nameBuffer, true, true) ) {
  796.  
  797.                         // create name registry full path for this printer and compare it
  798.                         // to the one thats stored in our rsrc
  799.                         
  800.                         // get the printers model
  801.                         GetIndString(modelString, kUSBModelPathString, *((**gGlobals).modelIndex+cell.v) );
  802.                         if( modelString[0] != 0 ) 
  803.                         {
  804.                             // create the path
  805.                             AppendPStr( (StringPtr) modelString, "\p:" );
  806.                             AppendPStr( (StringPtr) modelString, nameBuffer );
  807.                             // check to see if its the same
  808.                             HLock( printerString );
  809.                             if ( EqualString( modelString, (StringPtr) *printerString, true, true) )
  810.                                 foundCell = true;
  811.                             HUnlock( printerString );
  812.                         }
  813.                     }
  814.  
  815.                     if (!foundCell)
  816.                         cell.v++;
  817.                 } // end while
  818.             } // end else
  819.             break;
  820.         default:
  821.             break;
  822.     }
  823.     HUnlock( selectedPrinter );
  824.  
  825.     // if this is our first time and only 1 entry in the list and its USB then select it
  826.     if( ((**gGlobals).supportsUSB == true) && !foundCell && 
  827.         ((*list)->dataBounds.bottom == 1) && ((**gGlobals).numberOfUSBPrinters == 1) ) 
  828.     {
  829.         if( printerString != nil && (**printerString) == 0x0) {
  830.             SetPt(&cell, 0, 0);        // select the 1st cell
  831.  
  832.             if( SaveSelectedUSBPrinter( cell, list ) ) {
  833.                 // save the name of the printer
  834.                 SaveSelectedPrinterName( cell, list );
  835.                 foundCell = true;
  836.             }
  837.         }
  838.     }
  839.  
  840.     // now hilite the selection
  841.     if (foundCell)
  842.     {
  843.         LSetSelect(true, cell, list);
  844.         hiliteState = kHilited;
  845.     }
  846.  
  847.  
  848.     return noErr;
  849. }
  850.  
  851. /*-----------------------------------------------------------------------------*
  852.  
  853.     Select
  854.     
  855.     Desc:        Save the selected printers name and name registry path in our rsrc
  856.  
  857.     In:            - Handle to Mac List Mgr list
  858.                 - Name of zone we are currently in
  859.                 - the row Chooser thinks we should select.
  860.                 
  861.     Out:        OS error if any
  862.     
  863.     History:
  864.     
  865.     21 Mar 98    gp        Save printer name in our rsrc
  866.     24 Feb 98    gp        Created
  867.  
  868. *-----------------------------------------------------------------------------*/
  869. OSErr    Select (ListHandle list, StringPtr zoneName, long rowNum)
  870. {
  871.     
  872.     Str255            modelString;            // path in name registry of printer model
  873.     Handle            printerString=nil;        // path in name registry of current USB printer
  874.     Cell            selectedCell;            // for list processing
  875.     Str32            selectedPrinterName;    // select printer in list
  876.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  877.  
  878.     gGlobals = GetGlobalStorage();
  879.  
  880.     // Find out which row was selected
  881.     SetPt (&selectedCell, 0, 0);
  882.     LGetSelect (true, &selectedCell, list);
  883.  
  884.     // Get the name of the printer that was selected out of the list
  885.     GetNameFromCell (selectedPrinterName, selectedCell, list);
  886.  
  887.     // if nothing selected leave
  888.     if( selectedPrinterName[0] == 0 )
  889.         return noErr;
  890.  
  891.     // serial port selected so just clear the USB model path in the STR rsrc
  892.     if( selectedCell.v < (**gGlobals).numberOfPorts ) {
  893.         printerString = GetLastSelectedUSBPrinter();
  894.         (**printerString) = 0;
  895.         ChangedResource( printerString );
  896.         SetConnectionType( kSerial );
  897.         WriteResource(printerString);
  898.     } else {
  899.         SaveSelectedUSBPrinter( selectedCell, list );
  900.     }
  901.  
  902.     // save the name of the printer
  903.     SaveSelectedPrinterName( selectedCell, list );
  904.     return noErr;
  905. }
  906.  
  907. /*-----------------------------------------------------------------------------*
  908.  
  909.     InitPack
  910.     
  911.     Desc:        Creates our global storage and reads info out of our
  912.                 connection info rsrc
  913.  
  914.     In:            None
  915.  
  916.     Out:        OS error if any
  917.     
  918.     History:
  919.     
  920.     8  May 98    gp        If we don't support USB then no need to init the name registry
  921.                         ptrs. This will prevent the name registry alert from
  922.                         displaying on non PCI PowerMacs if we only support serial.
  923.     8  May 98    gp        Moved creation of model index to here from InitGlobalStorage
  924.     21 Apr 98    gp        If we don't support serial set numberOfPorts to zero
  925.     27 Mar 98    gp        Created
  926.  
  927.  *-----------------------------------------------------------------------------*/
  928. OSErr    InitPack(void)
  929. {
  930.     OSErr                returnValue            = noErr;    // return value
  931.     USBGlobalsHandle    gGlobals            = nil;        // our global data area
  932.     ConnectionTypeHdl    connectionInfo        = nil;
  933.     short                numberOfUSBPrinters = 0;        // number of USB printers detected
  934.     short                numberOfPorts        = 0;        // number of serial ports
  935.  
  936.     // initialize our global storage
  937.     returnValue = InitGlobalStorage();
  938.     if( returnValue == noErr ) 
  939.     {
  940.         gGlobals = GetGlobalStorage();
  941.         connectionInfo = (ConnectionTypeHdl) Get1Resource( kConnectionType, kConnectionTypeID );
  942.         if( connectionInfo != nil )
  943.         {
  944.             (**gGlobals).supportsSerial = ( (**connectionInfo).supportsSerial == 1 );
  945.             (**gGlobals).supportsUSB = ( (**connectionInfo).supportsUSB == 1 );
  946.  
  947.             // if we don't support serial ports then zero out serial port count
  948.             if( (**gGlobals).supportsSerial == false )
  949.                 (**gGlobals).numberOfPorts = 0;
  950.         }
  951.         
  952.         // count USB printers
  953.         if( (**gGlobals).supportsUSB == true )
  954.         {
  955.             // if we support USB we need to init proc ptrs before calling CountUSBPrinters
  956.             InitNameRegistryPtrs();
  957.  
  958.             numberOfUSBPrinters = CountUSBPrinters();
  959.             (**gGlobals).numberOfUSBPrinters = numberOfUSBPrinters;
  960.         } else {
  961.             numberOfUSBPrinters = 0;
  962.             (**gGlobals).numberOfUSBPrinters = 0;
  963.         }
  964.  
  965.         // count serial ports
  966.         if( (**gGlobals).supportsSerial == true ) {
  967.             numberOfPorts = CountSerialPorts();
  968.             (**gGlobals).numberOfPorts = numberOfPorts;
  969.         } else {
  970.             numberOfPorts = 0;
  971.             (**gGlobals).numberOfPorts = 0;
  972.         }
  973.  
  974.         // allocate our index storage
  975.         // there is index space for serial ports which are unused but make the code simpler
  976.         (**gGlobals).modelIndex = (short*) NewPtr( (numberOfPorts+numberOfUSBPrinters)*sizeof(short) );
  977.         if ( (**gGlobals).modelIndex == nil )
  978.         {
  979.             // no index storage so get rid of our globals too
  980.             RemoveGlobalStorage();
  981.             returnValue = memFullErr;
  982.         }
  983.  
  984.     }
  985.     return returnValue;
  986. }
  987.  
  988. /*-----------------------------------------------------------------------------*
  989.  
  990.     Chooser
  991.     
  992.     Desc:        Routines to handle calls from the Chooser
  993.  
  994.     In:            - message from chooser
  995.                 - application id
  996.                 - additional info (varies)
  997.                 - name of the appletalk zone
  998.                 - handle to device choices ( printers )
  999.                 - additional info (varies)
  1000.  
  1001.     Out:        OS error if any
  1002.     
  1003.     History:
  1004.     
  1005.     19 Mar 98    gp        Created
  1006.  
  1007.  *-----------------------------------------------------------------------------*/
  1008. pascal    OSErr    Chooser (short message, short caller, StringPtr objName, StringPtr zoneName, long p1, long p2)
  1009. {
  1010.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  1011.     OSErr returnValue = noErr;                // return value
  1012.  
  1013.     gGlobals = GetGlobalStorage();
  1014.     switch (message)
  1015.     {
  1016.         case chooserInitMsg:
  1017.             returnValue = InitPack();
  1018.             break;
  1019.         case fillListMsg:
  1020.             if( gGlobals != nil )
  1021.                 FillPrinterList( (ListHandle) p1 );
  1022.             break;
  1023.         case getSelMsg:
  1024.             if( gGlobals != nil )
  1025.                 ShowSelection ( (ListHandle)p1, zoneName);
  1026.             break;
  1027.         case selectMsg:
  1028.             if( gGlobals != nil )
  1029.                 Select ( (ListHandle)p1, zoneName, p2);
  1030.             break;
  1031.         case buttonMsg:
  1032.             break;
  1033.         case terminateMsg:
  1034.             RemoveNameRegistryPtrs();
  1035.             RemoveGlobalStorage();
  1036.             break;
  1037.         case deselectMsg:
  1038.             break;
  1039.         default:
  1040.             break;
  1041.     }
  1042.     return returnValue;
  1043. }
  1044.  
  1045. /*-----------------------------------------------------------------------------*
  1046.  
  1047.     InitGlobalStorage
  1048.     
  1049.     Desc:        Creates and stores a block of memory in our rsrc to be
  1050.                 used as global storage
  1051.  
  1052.     In:            none
  1053.  
  1054.     Out:        OS error if any
  1055.     
  1056.     History:
  1057.     
  1058.     10 Jun 98    gp        Lock our global area
  1059.     9  Jun 98    gp        Clear the handle when creating the global storage
  1060.                         Remove old global rsrc if its still there
  1061.     8  May 98    gp        Moved creation of model index to InitPack
  1062.     25 Mar 98    gp        Created
  1063.  
  1064.  *-----------------------------------------------------------------------------*/
  1065. OSErr    InitGlobalStorage(void)
  1066. {
  1067.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  1068.     Handle    globalrsrc;                        // handle to store our global data address
  1069.  
  1070.     // get rid of old global rsrc if its still there
  1071.     globalrsrc = (Handle) Get1Resource(kGlobalType, kGlobalID);
  1072.     if( globalrsrc != nil ) {
  1073.         RemoveResource( globalrsrc );
  1074.         DisposeHandle( globalrsrc );
  1075.     }
  1076.  
  1077.     // allocate our global storage
  1078.     gGlobals = (USBGlobalsHandle) NewHandleClear( sizeof( USBGlobals ) );
  1079.     globalrsrc = NewHandleClear( sizeof( Handle ) );
  1080.     if (gGlobals != nil) 
  1081.     {
  1082.         HLockHi( (Handle) gGlobals );
  1083.         // save our global handle address in our rsrc
  1084.         (** (Handle**) globalrsrc) = (char**) gGlobals;
  1085.         addresource( globalrsrc, kGlobalType, kGlobalID,(char*) "\p");
  1086.  
  1087.         return noErr;
  1088.     } else
  1089.         return memFullErr;
  1090. }
  1091.  
  1092. /*-----------------------------------------------------------------------------*
  1093.  
  1094.     GetGlobalStorage
  1095.     
  1096.     Desc:        Retrieves our global stoarge area
  1097.  
  1098.     In:            none
  1099.  
  1100.     Out:        Handle to our global storage
  1101.     
  1102.     History:
  1103.     
  1104.     25 Mar 98    gp        Created
  1105.  
  1106.  *-----------------------------------------------------------------------------*/
  1107. USBGlobalsHandle    GetGlobalStorage(void)
  1108. {
  1109.     Handle    ourRsrc=nil;                    // handle to ourselves
  1110.  
  1111.     ourRsrc = (Handle) Get1Resource(kGlobalType, kGlobalID);
  1112.     if( ourRsrc == nil )
  1113.         return nil;
  1114.     
  1115.     return (**(USBGlobalsHandle**)ourRsrc);
  1116. }
  1117.  
  1118. /*-----------------------------------------------------------------------------*
  1119.  
  1120.     RemoveGlobalStorage
  1121.     
  1122.     Desc:        Removes our global storage area
  1123.  
  1124.     In:            none
  1125.  
  1126.     Out:        Handle to our global storage
  1127.     
  1128.     History:
  1129.     
  1130.     9  Jun 98    gp        Dispose of our global rsrc after removing it
  1131.     26 Mar 98    gp        Release model index storage
  1132.     25 Mar 98    gp        Created
  1133.  
  1134.  *-----------------------------------------------------------------------------*/
  1135. void    RemoveGlobalStorage(void)
  1136. {
  1137.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  1138.     Handle                ourRsrc;
  1139.     
  1140.     gGlobals = GetGlobalStorage();
  1141.     if( gGlobals != nil ) {
  1142.         // dispose of index ptr
  1143.         
  1144.         if ( (**gGlobals).modelIndex != nil )
  1145.         {
  1146.             DisposePtr( (Ptr) (**gGlobals).modelIndex );
  1147.         }
  1148.              
  1149.         // remove our global handle
  1150.         HUnlock( (Handle) gGlobals );
  1151.         DisposeHandle( (Handle) gGlobals );
  1152.         // remove our rsrc for global address storage
  1153.         ourRsrc = (Handle) Get1Resource(kGlobalType, kGlobalID);
  1154.         RemoveResource( ourRsrc );
  1155.         DisposeHandle( ourRsrc );
  1156.     }
  1157. }
  1158. // eof
  1159.